package cn.zhfeat.hatch.web.shiro;



import cn.zhfeat.hatch.dto.sysuser.SysRoleAuthorityDto;
import cn.zhfeat.hatch.dto.sysuser.SysUserDto;
import cn.zhfeat.hatch.dto.sysuser.SysUserRoleDto;
import cn.zhfeat.hatch.entity.sysuser.SysRoleAuthority;
import cn.zhfeat.hatch.entity.sysuser.SysUser;
import cn.zhfeat.hatch.entity.sysuser.SysUserRole;
import cn.zhfeat.hatch.rpc.IAccountRpcService;
import cn.zhfeat.hatch.rpc.IRoleRpcService;
import org.apache.shiro.authc.*;
import org.apache.shiro.authz.AuthorizationInfo;
import org.apache.shiro.authz.SimpleAuthorizationInfo;
import org.apache.shiro.realm.AuthorizingRealm;
import org.apache.shiro.subject.PrincipalCollection;
import org.springframework.beans.factory.annotation.Autowired;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletRequest;

import java.util.HashSet;
import java.util.List;
import java.util.Set;

/**
 * @description: 用户自定义的登录验证及授权Realm
 *
 * @author ZhangHao
 * @date 2018年5月14日 上午11:20:41 
 * @version 1.0.0.1
 */
public class ShiroRealm extends AuthorizingRealm {

	
	
	@Resource
	private HttpServletRequest request;

	@Autowired
	private IAccountRpcService accountRpcService;
	
	@Autowired
	private IRoleRpcService roleRpcService;



	/**
	 * 权限认证 当需要检查用户权限时自动调用此方法。注意：该权限控制的是访问权限，不是菜单权限和数据权限
	 */
	@Override
	protected AuthorizationInfo doGetAuthorizationInfo(
			PrincipalCollection principals) {
		
		//根据用户名获取到他所拥有的角色以及权限，然后赋值到SimpleAuthorizationInfo对象中即可，Shiro就会按照我们配置的XX角色对应XX权限来进行判断
		SimpleAuthorizationInfo authorizationInfo = new SimpleAuthorizationInfo();
         //获取用户名，然后根据用户名从数据库找到该用户的所有权限，取并集,PrincipalCollection这个可以理解为当事人的信息,登陆后会传递这个信息到doGetAuthorizationInfo方法
        SysUser user = (SysUser) getAvailablePrincipal(principals);
         //获取用户信息

        // 从数据库获取用户权限
	    Set<String> permissions = new HashSet<String>();
		//不管什么权限的用户登录，都会add一个login,登陆权限
		permissions.add("login");
		
		//酷客平台权限不需要控制在角色范围上，只控制到菜单范围，所以这里只对菜单做处理
		
		//根据用户ID获取用户的全部角色
		SysUserRoleDto dto = new SysUserRoleDto();
		dto.setUserId(user.getId());
		List<SysUserRole> sysUserRoles = accountRpcService.selectSysUserRoles(dto);
		//根据用户的角色查询出用户对应的全部菜单，遍历全部菜单标识，放入permissions,后续交由shiro过滤链过滤使用
		for(int i=0;i<sysUserRoles.size();i++) {
			SysRoleAuthorityDto sysRoleAuthorityDto = new SysRoleAuthorityDto();
			sysRoleAuthorityDto.setRoleId(sysUserRoles.get(i).getRoleId());
			sysRoleAuthorityDto.setIsDeleted(0);
			List<SysRoleAuthority> s = roleRpcService.findSysRoleAuthorityByDto(sysRoleAuthorityDto);
			for(int o=0;o<s.size();o++) {
				permissions.add(s.get(o).getAuthorityNameEn());
			}
		}
		
		// 为该用户权限
		authorizationInfo.setStringPermissions(permissions);
		// 返回权限信息
		return authorizationInfo;
	}


	/**
	 * 身份认证 当用户需要身份认证时会自动调用这个方法
	 */
	@Override
	protected AuthenticationInfo doGetAuthenticationInfo(
			AuthenticationToken token) throws AuthenticationException {
		// 1.获取用户名、密码
		UsernamePasswordToken upt = (UsernamePasswordToken) token;
		String loginName = upt.getUsername();

		// 用户名
		String username = upt.getUsername();
		// 密码
		String password = new String((char[]) upt.getPassword());

		// 用户请求的用户名
		// 用户请求的密码
		SysUserDto dto = new SysUserDto();
		dto.setAccount(username);
		// 2.从数据库查询用户信息
		SysUser user = accountRpcService.findUserInfoByType(dto);

		// 3.将获取的用户名密码和数据库用户名密码进行比对
		if (user != null) {
			SimpleAuthenticationInfo saInfo = new SimpleAuthenticationInfo(user, user.getPwd(), this.getName());
			return saInfo;
		}
		// 4身份验证通过,返回一个身份信息

		return null;
	}

	/**
	 * @description: 根据principals获取缓存的key
	 *
	 * @param principals
	 * @return 
	 * @author ZhangHao
	 * @date 2018年5月26日 上午9:22:44 
	 * @version 1.0.0.1
	 */
	@Override
	protected Object getAuthorizationCacheKey(PrincipalCollection principals) {

		SysUser sysUser = (SysUser) principals.getPrimaryPrincipal();

		return sysUser.getId();
	}
}
